package com.bifang.module.file.core.util;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import com.bifang.module.file.common.vo.FileClassVO;
import com.bifang.module.file.common.vo.FileInfoVO;
import com.github.tobato.fastdfs.domain.fdfs.MetaData;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.domain.upload.FastFile;
import com.bifang.engine.assistant.core.enums.BoolEnum;
import com.bifang.engine.assistant.core.exception.AppException;
import com.bifang.module.file.common.util.Encode;
import com.bifang.module.file.common.util.FastDFSClient;
import com.bifang.module.file.common.vo.FileMetadataVO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

@Component
public class FileFastDfsUtil {
    protected Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired private FileCommonUtil fileCommonUtil;
    @Autowired private FastDFSClient fastDFSClient;

    /** fastdfs上传 */
    public Boolean upload(File file, FileClassVO fileClassVO, FileInfoVO fileInfoVO) {
        // String confUrl =
        // this.getClass().getClassLoader().getResource("/config/fdfs_client.properties").getPath();
        // 1、把FastDFS提供的jar包添加到工程中
        // 2、初始化全局配置。加载一个配置文件。
        FastFile fastFile =null;
        try {
            fileCommonUtil.initFile(file, fileClassVO, fileInfoVO);
            // 校验文件是否可以上传
            fileCommonUtil.checkFile(
                    fileInfoVO.getFileSuffix(), fileInfoVO.getFileSize(), fileClassVO);
            if (StringUtils.isNotBlank(fileInfoVO.getEncryptionFlag())) {
                if (BoolEnum.TRUE.getType().endsWith(fileInfoVO.getEncryptionFlag())) {
                    fileInfoVO.setFilePassowrd(RandomUtil.randomString(5));
                    new Encode(true, file, fileInfoVO.getFilePassowrd()).run();
                }
            } else {
                fileInfoVO.setEncryptionFlag(BoolEnum.FALSE.getType());
            }

            fastFile = getFastFile(file, fileInfoVO);
            fileInfoVO.setOtherStartTime(new Date());
            StorePath storePath = fastDFSClient.uploadFile(fastFile);
            fileInfoVO.setOtherEndTime(new Date());
            if (StringUtils.isBlank(storePath.getFullPath())) {
                return false;
            }
            fileInfoVO.setStorageGroup(storePath.getGroup());
            fileInfoVO.setFilePath(storePath.getPath());
            return true;
        } catch (Exception e) {
            throw new AppException("上传文件失败:" + e.getMessage());
        }finally {
            if(fastFile!=null){
                InputStream inputStream=fastFile.getInputStream();
                if(inputStream!=null){
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    /** fastdfs上传 */
    public Boolean upload(byte[] file, FileClassVO fileClassVO, FileInfoVO fileInfoVO) {
        Boolean flag = true;
        InputStream sbs = new ByteArrayInputStream(file);
        try {
            fileCommonUtil.initFile(sbs, fileClassVO, fileInfoVO);
            // 校验文件是否可以上传
            fileCommonUtil.checkFile(
                    fileInfoVO.getFileSuffix(), fileInfoVO.getFileSize(), fileClassVO);

            if (StringUtils.isNotBlank(fileInfoVO.getEncryptionFlag())) {
                if (BoolEnum.TRUE.getType().endsWith(fileInfoVO.getEncryptionFlag())) {
                    String fileName = getFileName(fileInfoVO);
                    fileInfoVO.setFilePassowrd(RandomUtil.randomString(5));
                    File tempFile = fileCommonUtil.createTempFile(sbs, fileName);
                    new Encode(true, tempFile, fileInfoVO.getFilePassowrd()).run();
                    flag = upload(fileInfoVO, tempFile);
                    return flag;
                }
            }

            FastFile fastFile = getFastFile(file, fileInfoVO);
            fileInfoVO.setOtherStartTime(new Date());
            StorePath storePath = fastDFSClient.uploadFile(fastFile);
            fileInfoVO.setOtherEndTime(new Date());
            if (StringUtils.isBlank(storePath.getFullPath())) {
                return false;
            }
            fileInfoVO.setStorageGroup(storePath.getGroup());
            fileInfoVO.setFilePath(storePath.getPath());
        } catch (Exception e) {
            throw new AppException("上传文件失败:" + e.getMessage());
        } finally {

            if (sbs != null) {
                try {
                    sbs.close();
                } catch (IOException e) {
                    logger.error("关闭流异常，", e);
                }
            }
        }
        return flag;
    }

    /** fastdfs上传 */
    public Boolean upload(InputStream in, FileClassVO fileClassVO, FileInfoVO fileInfoVO) {
        Boolean flag = true;

        try {
            fileCommonUtil.initFile(in, fileClassVO, fileInfoVO);
            // 校验文件是否可以上传
            fileCommonUtil.checkFile(
                    fileInfoVO.getFileSuffix(), fileInfoVO.getFileSize(), fileClassVO);
            if (StringUtils.isNotBlank(fileInfoVO.getEncryptionFlag())) {
                if (BoolEnum.TRUE.getType().endsWith(fileInfoVO.getEncryptionFlag())) {
                    String fileName = this.getFileName(fileInfoVO);
                    File file = fileCommonUtil.createTempFile(in, fileName);
                    fileInfoVO.setFilePassowrd(RandomUtil.randomString(5));
                    new Encode(true, file, fileInfoVO.getFilePassowrd()).run();
                    flag = upload(fileInfoVO, file);
                    return flag;
                }
            } else {
                fileInfoVO.setEncryptionFlag(BoolEnum.FALSE.getType());
            }
            FastFile fastFile = getFastFile(in, fileInfoVO);
            fileInfoVO.setOtherStartTime(new Date());
            StorePath storePath = fastDFSClient.uploadFile(fastFile);
            fileInfoVO.setOtherEndTime(new Date());
            if (StringUtils.isBlank(storePath.getFullPath())) {
                return false;
            }
            fileInfoVO.setStorageGroup(storePath.getGroup());
            fileInfoVO.setFilePath(storePath.getPath());

        } catch (Exception e) {
            logger.error("上传文件失败，", e);
            throw new AppException("上传文件失败:" + e.getMessage());
        } finally {

            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    logger.error("关闭流异常，", e);
                }
            }
        }
        return flag;
    }

    private Boolean upload(FileInfoVO fileInfoVO, File file) {
        Boolean flag = true;
        FastFile fastFile = getFastFile(file, fileInfoVO);
        fileInfoVO.setOtherStartTime(new Date());
        StorePath storePath = fastDFSClient.uploadFile(fastFile);
        fileInfoVO.setOtherEndTime(new Date());
        if (StringUtils.isBlank(storePath.getFullPath())) {
            flag = false;
        } else {
            flag = true;
        }
        // 删除临时文件
        fileCommonUtil.delTempFile(file);
        return flag;
    }

    /** fastdfs文件下载 */
    public File download(FileInfoVO fileInfoVO) {
        String fileName = fileInfoVO.getFileMd5() + "." + fileInfoVO.getFileSuffix();
        if (fileInfoVO.getForceFlag() != null && fileInfoVO.getForceFlag()) {
            fileCommonUtil.delTempFileDownloadByName(fileName);
        }
        File file = fileCommonUtil.createTempFileDownload(fileName);
        if (file.length() <= 0) {
            // 空文件重新下载
            fastDFSClient.download(fileInfoVO.getStorageGroup(), fileInfoVO.getFilePath(), file);
            // 解密文件
            if (BoolEnum.TRUE.getType().equals(fileInfoVO.getEncryptionFlag())) {
                new Encode(false, file, fileInfoVO.getFilePassowrd()).run();
            }
        }
        return file;
    }
    public void download(FileInfoVO fileInfoVO,HttpServletResponse response) {
        String fileName = fileInfoVO.getFileName();
        if(StringUtils.isBlank(fileName)){
            fileName=fileInfoVO.getFileMd5() + "." + fileInfoVO.getFileSuffix();
        }
        fastDFSClient.download(fileName,fileInfoVO.getStorageGroup(), fileInfoVO.getFilePath(), response);

    }
    /** fastdfs文件下载 */
    public byte[] download_byte(FileInfoVO fileInfoVO) {
        // 解密文件
        if (BoolEnum.TRUE.getType().equals(fileInfoVO.getEncryptionFlag())) {
            String fileName = fileInfoVO.getFileMd5() + "." + fileInfoVO.getFileSuffix();
            if (fileInfoVO.getForceFlag()) {
                fileCommonUtil.delTempFileDownloadByName(fileName);
            }
            File file = fileCommonUtil.createTempFileDownload(fileName);
            if (file.length() <= 0) {
                // 空文件重新下载
                fastDFSClient.download(
                        fileInfoVO.getStorageGroup(), fileInfoVO.getFilePath(), file);
            }
            new Encode(false, file, fileInfoVO.getFilePassowrd()).run();
            return FileUtil.readBytes(file);
        } else {
            return fastDFSClient.downloadFile(
                    fileInfoVO.getStorageGroup(), fileInfoVO.getFilePath());
        }
    }

    public String getBase64(FileInfoVO fileInfoVO) {
        byte[] bytes = this.download_byte(fileInfoVO);
        if (bytes == null) {
            throw new AppException("文件不存在");
        }
        int length = bytes.length;
        fileCommonUtil.checkBase64((long) length);
        return Base64.encode(bytes);
    }

    /** 删除文件 */
    public void delete(FileInfoVO fileInfoVO) {
        fastDFSClient.deleteFile(fileInfoVO.getStorageGroup(), fileInfoVO.getFilePath());
    }

    /** 显示文件 */
    public String show(FileInfoVO fileInfoVO, HttpServletResponse response) {
        String groupName = fileInfoVO.getStorageGroup();
        String path = fileInfoVO.getFilePath();
        if (StringUtils.isBlank(groupName)) {
            throw new AppException("数据异常：fastdfs组信息未配置");
        }
        if (StringUtils.isBlank(path)) {
            throw new AppException("数据异常：文件具体路径未找到");
        }
        /***减少服务开销，不去查找
        FileInfo fileInfo = fastDFSClient.queryFileInfo(groupName, path);
        if (fileInfo == null) {
            throw new AppException("未找到文件");
        }***/
        return "/" + groupName + "/" + path;
    }

    private String getFileName(FileInfoVO fileInfoVO) {
        return fileInfoVO.getFileMd5() + "." + fileInfoVO.getFileSuffix();
    }

    private FastFile getFastFile(byte[] file, FileInfoVO fileInfoVO) {
        InputStream inputStream = new ByteArrayInputStream(file);
        return getFastFile(inputStream, fileInfoVO);
    }

    private FastFile getFastFile(File file, FileInfoVO fileInfoVO) {
        InputStream inputStream = FileUtil.getInputStream(file);
        return getFastFile(inputStream, fileInfoVO);
    }

    private FastFile getFastFile(InputStream in, FileInfoVO fileInfoVO) {
        Set<MetaData> metaDataSet = null;
        if (!CollectionUtils.isEmpty(fileInfoVO.getMetadataList())) {
            metaDataSet = new HashSet<>();
            for (FileMetadataVO fileMetadataVO : fileInfoVO.getMetadataList()) {
                String name = "";
                if (StringUtils.isNotBlank(fileMetadataVO.getFieldKey())) {
                    name = fileMetadataVO.getFieldKey();
                    if (StringUtils.isNotBlank(fileMetadataVO.getFieldName())) {
                        name = name + "-" + fileMetadataVO.getFieldName();
                    }
                } else {
                    name = fileMetadataVO.getFieldName();
                }
                String value = "";
                if (StringUtils.isNotBlank(fileMetadataVO.getFieldValue())) {
                    value = fileMetadataVO.getFieldValue();
                    if (StringUtils.isNotBlank(fileMetadataVO.getFieldText())) {
                        value = value + "-" + fileMetadataVO.getFieldText();
                    }
                }
                if (StringUtils.isNotBlank(name) && StringUtils.isNotBlank(value)) {
                    MetaData metaData = new MetaData();
                    metaData.setName(name);
                    metaData.setValue(value);
                    metaDataSet.add(metaData);
                }
            }
        }
        FastFile.Builder builder = new FastFile.Builder();
        if (StringUtils.isNotBlank(fileInfoVO.getStorageGroup())) {
            builder.toGroup(fileInfoVO.getStorageGroup());
        }
        builder.withFile(in, fileInfoVO.getFileSize(), fileInfoVO.getFileSuffix());
        if (!CollectionUtils.isEmpty(metaDataSet)) {
            builder.withMetaData(metaDataSet);
        }
        FastFile fastFile = builder.build();
        return fastFile;
    }
}
